package com.borrowed.book.book.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.borrowed.book.book.Exception.UnderStockException;
import com.borrowed.book.book.Exception.UnexpectOrderException;
import com.borrowed.book.book.constant.BookConstant;
import com.borrowed.book.book.domain.*;
import com.borrowed.book.book.entity.domain.vo.PayOrderBaseInVo;
import com.borrowed.book.book.entity.domain.vo.PayOrderBaseOutVo;
import com.borrowed.book.book.entity.domain.vo.PayOrderCreateInVo;
import com.borrowed.book.book.mapper.SBookMapper;
import com.borrowed.book.book.mapper.SPayOrderDetailMapper;
import com.borrowed.book.book.mapper.SPayOrderMapper;
import com.borrowed.book.book.service.AbstractPayOrderService;
import com.borrowed.book.book.service.BorrowOrderService;
import com.borrowed.book.book.service.SBookService;
import com.borrowed.book.book.util.PayorderUtil;
import com.borrowed.book.coupon.entity.SCoupon;
import com.borrowed.book.coupon.service.SCouponService;
import com.borrowed.book.coupon.service.SCouponUserService;
import com.borrowed.book.membercard.entity.SMemberCard;
import com.borrowed.book.membercard.entity.SMembercardUser;
import com.borrowed.book.membercard.service.SMemberCardService;
import com.borrowed.book.membercard.service.SMembercardUserService;
import com.borrowed.book.system.domain.SysDictPojo;
import com.borrowed.book.system.service.ISysDictService;
import com.borrowed.book.system.util.DayUtil;
import com.borrowed.book.user.domain.SUser;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * 图书订单服务
 */
@Service
public class BookPayorderServiceImpl extends AbstractPayOrderService {
    @Autowired
    private SBookMapper bookMapper;
    @Autowired
    private ISysDictService dictService;
    @Autowired
    private SMembercardUserService membercardUserService;
    @Autowired
    private SMemberCardService memberCardService;
    @Autowired
    private SCouponService couponService;
    @Autowired
    private SCouponUserService couponUserService;
    @Autowired
    private SPayOrderMapper payOrderMapper;
    @Autowired
    private SBookService bookService;
    @Autowired
    private SPayOrderDetailMapper payOrderDetailMapper;
    @Autowired
    private BorrowOrderService borrowOrderService;

    @Override
    public PayOrderBaseOutVo initialPayorderInfo(PayOrderBaseInVo payorderBaseInVo) {
        InitalBookPayOutDtoOut outDto=new InitalBookPayOutDtoOut();
        InitialBookPayInDto param=(InitialBookPayInDto)payorderBaseInVo;
        //计算收发货日期
        PayorderUtil.calculateDate(outDto);
        //图书信息
        Map<String,Object> map=new HashMap<>();
        map.put("bookIds",param.getBookIds());
        List<InitialBookPayDto> bookData=bookMapper.selectBookListForPay(map);
        outDto.setBookData(bookData);
        //押金
        BigDecimal cashPledge=new BigDecimal(0);
        for(InitialBookPayDto book:bookData){
            cashPledge=cashPledge.add(book.getPrice());
        }
        outDto.setCashPledge(cashPledge);
        //原始租金
        BigDecimal rentMoney=bookMapper.selectBorrowRentMoney(map);
        outDto.setRentMoneyOri(rentMoney);
        //安心租
        if("1".equals(param.getRestFlag())){
            List<SysDictPojo> sysDicts=dictService.getDictByType("restRatio");
            outDto.setRestMoney(rentMoney.multiply(new BigDecimal(sysDicts.get(0).getKey())));
        }
        //支付方式-会员卡1  直购2
        if(param.getPayType()==2){//直购
            outDto.setRentMoney(rentMoney);
        }else if(param.getPayType()==1){
            //查询当前登录用户是否是会员,会员租金免费
            Boolean memberFlag=false;
            SMembercardUser memcardUser=membercardUserService.getCurrentMembercardUser();
            if(memcardUser!=null){
                    memberFlag=true;
            }
            if(memberFlag) {
                outDto.setRentMoney(new BigDecimal(0));
            }else{
                outDto.setRentMoney(rentMoney);
            }
        }
        //运费
        SysDictPojo sysDict=dictService.getDictByTypeAndKey("costType","postAmount");
        outDto.setPostage(new BigDecimal(sysDict.getValue()));
        //优惠券
        if(param.getCouponId()==null) {
            //年会会员，查询对应的有效的优惠券
            if(param.getUseCoupon()) {
                SelectUserCouponInDto couponInDto=new SelectUserCouponInDto();
                couponInDto.setCouponStatus(BookConstant.COUPON_STATUS_UNUSE);
                couponInDto.setCouponType( BookConstant.COUPON_TYPE_THREE);
                List<SCouponDto>  couponList=couponService.selectUserCoupon(couponInDto);
                if (couponList != null&&couponList.size()>0) {
                    couponList.get(0).setRemainDays(DayUtil.daysBetween(new Date(), couponList.get(0).getValidEndTime()));
                    outDto.setCoupon(couponList.get(0));
                }
            }
        }else{
            //传入选中的优惠券，重新计算结算价格
            SCoupon coupon =couponService.getById(param.getCouponId());
            SCouponDto couponDto=new SCouponDto();
            BeanUtils.copyProperties(coupon,couponDto);
            couponDto.setRemainDays(DayUtil.daysBetween(new Date(), coupon.getValidEndTime()));
            outDto.setCoupon(couponDto);
        }
        //总价 押金+租金+运费-优惠券
        outDto.setPayAmount(cashPledge.add(outDto.getRentMoney()).add(outDto.getPostage()));
        if(outDto.getCoupon()!=null){
            outDto.setPayAmount(cashPledge.add(outDto.getRentMoney()).add(outDto.getPostage()).subtract(outDto.getCoupon().getFaceValue()));
        }
        //安心租
        if("1".equals(param.getRestFlag())){
            outDto.setPayAmount(outDto.getPayAmount().add(outDto.getRestMoney()));
        }
        return outDto;
    }

    @Override
    public String createPayorder(PayOrderCreateInVo payOrderCreateInVo) throws UnexpectOrderException {
        SUser sysUser = (SUser) SecurityUtils.getSubject().getPrincipal();
        PayOrderInDto param=(PayOrderInDto)payOrderCreateInVo;
        //查询当前用户未完成的借书订单--待发货、待收货、待归还、待结算
        List<String> statusList=Arrays.asList(BookConstant.UN_PAY,BookConstant.TO_SEND_PAY,BookConstant.TO_RECEIVE_PAY,BookConstant.TO_RETURN_PAY,BookConstant.TO_CLOSE_PAY);
        Map<String,Object> map=new HashMap<>();
        map.put("openid",sysUser.getOpenid());
        map.put("statusList",statusList);
        Long orderCount=payOrderMapper.selectPayOrderByStatus(map);
        //检查会员级别，年度会员同时两单，其它会员只能同时一单
        SMembercardUser memcardUser=membercardUserService.getCurrentMembercardUser();
        if(memcardUser==null){
            if (orderCount >= 1) {
                throw new UnexpectOrderException("普通用户、非年度会员最多同时借一单");
            }
        }else{
            if(orderCount>=memcardUser.getBorrowTimes()){
                SMemberCard cardInfo=memberCardService.getById(memcardUser.getCardId());
                throw new UnexpectOrderException(cardInfo.getCardName()+"最多同时借"+memcardUser.getBorrowTimes()+"单");
            }
        }
        //如果使用了优惠券，更新优惠券状态为使用中
        if(param.getCouponId()!=null){
            UpdateWrapper updateWrapper=new UpdateWrapper();
            updateWrapper.eq("id",param.getCouponId());
            updateWrapper.set("coupon_status",BookConstant.COUPON_STATUS_INUSE);
            couponUserService.update(updateWrapper);
        }
        //创建订单编号
        String orderNo=PayorderUtil.createOrderNo();
        SPayOrder payOrder=new SPayOrder();
        BeanUtils.copyProperties(param,payOrder);

        payOrder.setOpenid(sysUser.getOpenid());
        payOrder.setOrderNo(orderNo);
        payOrder.setOrderStatus(BookConstant.UN_PAY);
        payOrder.setCreateTime(new Date());
        if(BookConstant.RENT_ORDER.equals(param.getOrderType())){
            //预计发货时间
            Calendar calendar=Calendar.getInstance();
            calendar.setTime(new Date());
            //借阅开始时间
            calendar.set(Calendar.DAY_OF_MONTH,calendar.get(Calendar.DAY_OF_MONTH)+3); //默认第三天借阅开始
            payOrder.setBorrowStartTime(calendar.getTime());
            //借阅结束时间
            calendar.set(Calendar.MONTH,calendar.get(Calendar.MONTH)+1);//默认借阅一个月
            payOrder.setBorrowEndTime(calendar.getTime());
        }
        payOrderMapper.insert(payOrder);
        //插入订单详细数据
        for(Long  bookId:param.getBookIds()){
            //借书订单，则检查库存
            SelectBookOutDto bookInfo=null;
            try {
                bookService.CheckBookRemaining(bookId);
            } catch (UnderStockException e) {
                throw new UnexpectOrderException(e.getMessage());
            }
            //书籍库存量减1
            bookMapper.reduceBookRemaining(bookId);
            //订单详细
            SPayOrderDetail  payOrderDetail=new SPayOrderDetail();
            payOrderDetail.setGoodId(bookId);
            payOrderDetail.setOrderNo(orderNo);
            payOrderDetail.setGoodPrice(bookInfo.getPrice());
            payOrderDetailMapper.insert(payOrderDetail);
            //移除书架
            try {
                borrowOrderService.deleteBorrowOrderById(bookId);
            }catch (Exception e){
                throw new UnexpectOrderException(e.getMessage());
            }
        }
        return orderNo;
    }

    @Override
    public Boolean cancelPayorder(String orderNo) {
        SUser sysUser = (SUser) SecurityUtils.getSubject().getPrincipal();
        SelectPayOrderOutDto orderInfo=payOrderMapper.selectPayOrderById(orderNo);
        //优惠券  状态更新为待使用
        if(orderInfo.getCouponId()!=null) {
            UpdateWrapper updateWrapper = new UpdateWrapper();
            updateWrapper.eq("id", orderInfo.getCouponId());
            updateWrapper.set("coupon_status", BookConstant.COUPON_STATUS_UNUSE);
            couponUserService.update(updateWrapper);
        }
        //解绑优惠券id,订单状态更新为已取消
        Map<String,Object> map=new HashMap<>();
        map.put("openid",sysUser.getOpenid());
        map.put("orderNo",orderNo);
        map.put("payStatus",BookConstant.CANCELL_PAY);
        payOrderMapper.cancelPayOrder(map);
        List<BookOrderDetailDto> payOrderDetailList = payOrderDetailMapper.selectBookListByOrderNo(orderNo);
        for (BookOrderDetailDto detail : payOrderDetailList) {
            //若是借书订单，则库存增加1
            bookMapper.increaseBookRemaining(detail.getGoodId());
        }
        return true;
    }




}
